package com.shiku.im.redpack.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.shiku.common.model.PageResult;
import com.shiku.commons.thread.ThreadUtils;
import com.shiku.im.comm.constants.KConstants;
import com.shiku.im.comm.model.MessageBean;
import com.shiku.im.comm.utils.BeanUtils;
import com.shiku.im.comm.utils.ReqUtil;
import com.shiku.im.common.service.RedPacketsManager;
import com.shiku.im.message.MessageService;
import com.shiku.im.message.MessageType;
import com.shiku.im.pay.constants.PayResultCode;
import com.shiku.im.pay.dao.ConsumeRecordDao;
import com.shiku.im.pay.entity.BaseConsumeRecord;
import com.shiku.im.pay.entity.ConsumeRecord;
import com.shiku.im.redpack.dao.RedPacketDao;
import com.shiku.im.redpack.dao.RedReceiveDao;
import com.shiku.im.redpack.dto.SendRedPacketDTO;
import com.shiku.im.redpack.entity.RedPacket;
import com.shiku.im.redpack.entity.RedReceive;
import com.shiku.im.room.dao.RoomCoreDao;

import com.shiku.im.room.dao.RoomCoreDao;
import com.shiku.im.entity.Config;

import com.shiku.im.room.entity.Room;
import com.shiku.im.room.entity.RoomChanceSettings;
import com.shiku.im.room.service.impl.RoomChanceSettingsServiceImpl;
import com.shiku.im.room.service.impl.RoomManagerImplForIM;
import com.shiku.im.user.dao.impl.UserChanceSettingsServiceImpl;
import com.shiku.im.user.entity.User;
import com.shiku.im.user.entity.UserChanceSettings;
import com.shiku.im.user.entity.UserMoneyLog;
import com.shiku.im.user.constants.MoneyLogConstants.*;
import com.shiku.im.user.service.UserCoreService;
import com.shiku.im.user.service.impl.UserCoreServiceImpl;
//import com.shiku.im.user.service.impl.UserManagerImpl;
import com.shiku.im.utils.SKBeanUtils;
import com.shiku.im.vo.JSONMessage;
import com.shiku.mongodb.utils.BeanCopyUtils;
import com.shiku.redisson.ex.LockFailException;
import com.shiku.utils.DateUtil;
import com.shiku.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import springfox.documentation.spring.web.json.Json;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.util.stream.Collectors;

import java.text.DecimalFormat;
import java.util.*;

@Slf4j
@Service
public class RedPacketManagerImpl implements RedPacketsManager {

	@Autowired
	private RedPacketDao redPacketDao;

	@Autowired
	private RedReceiveDao redReceiveDao;

	@Autowired
	private ConsumeRecordDao consumeRecordDao;

	@Autowired
	private RoomCoreDao roomCoreDao;

	@Autowired
	private UserCoreService userCoreService;

	@Autowired
	private MessageService messageService;


	@Autowired
	private RedPacketRedisService redPacketRedisService;
	@Autowired
	private UserChanceSettingsServiceImpl userChanceSettingsService;
	@Autowired
	private RoomChanceSettingsServiceImpl roomChanceSettingsService;
	
	@Autowired
	private RoomManagerImplForIM roomManager;

//	@Autowired
//	private UserManagerImpl userManager;



	
	public RedPacket saveRedPacket(RedPacket entity){
			redPacketDao.addRedPacket(entity);
			return entity;
	}

	public Object sendRedPacket(int userId, RedPacket packet) throws Exception {

		try {
			return userCoreService.payMoenyBalanceOnLock(userId, packet.getMoney(), obj -> {
				return sendRedPacketOnLock(userId, packet);
			});
		} catch (Exception e) {
			throw e;
		}


	}

	public Object sendRedPacket(int userId, SendRedPacketDTO packetDTO) throws Exception {

		try {
			RedPacket packet = new RedPacket();
			BeanUtils.copyProperties(packetDTO, packet);
			packet.setGreetingsCopy(packet.getGreetings());
			packet.setSenderWin(getWin(packet));
//			packet.setGreetingsCopy(packet.getGreetings() + "?" + packet.isSenderWin());
			return userCoreService.payMoenyBalanceOnLock(userId, packet.getMoney(), obj -> {
				return sendRedPacketOnLock(userId, packet);
			});
		} catch (Exception e) {
			throw e;
		}


	}

	private boolean getWin(RedPacket packet) {
		//判断是否为拼手气红包
		if (packet.getType() == 2) {
			try {
				Config config = SKBeanUtils.getSystemConfig();
				double reallyProbability = getReallyProbability(packet);
				//新增 start
				BigDecimal bigDecimal = new BigDecimal(reallyProbability);
				BigDecimal result = bigDecimal.setScale(8, BigDecimal.ROUND_HALF_UP);
				double realProb = result.doubleValue();
				double winProbability = getWinProbabilityV2(packet, realProb);
				//新增 end
//				int winProbability = getWinProbability(packet);
//				double finalProbability = (reallyProbability + ((winProbability - 50) / 100.0) * 2 * (1 - reallyProbability)) * 100;
				//赢率微调数值
//				double winProbabilityType = config.getWinProbabilityType();
//				double finalProbability2 = ((finalProbability / 100) + ((winProbabilityType - 50) / 100.0) * 2 * (1 - (finalProbability / 100))) * 100;
//                double finalProbability2 = (finalProbability * (100 + winProbabilityType))/100;
//				double random = Math.random() * 100;
				double random = Math.random();
				if (winProbability >= random) {
					String title = packet.getGreetingsCopy();
					int count = packet.getCount();
					int[] nums = getNums(title);
					List<Integer> numsList = Arrays.stream(nums).boxed().collect(Collectors.toList());
					ArrayList<Integer> winCount = new ArrayList<>();
					for (int i = 0; i < packet.getCount(); i++) {
						winCount.add(-1);
					}
					int[] v = randomCommon(0, count - 1 - 1, nums.length);
					for (int i = 0; i < v.length; i++) {
						int n = RANDOM.nextInt(numsList.size());
						winCount.set(v[i], numsList.get(n));
						numsList.remove(n);
					}
					packet.setGreetingsCopy("真" + reallyProbability + "设" + winProbability);
					packet.setWinCount(winCount);
//					packet.setGreetingsCopy(packet.getGreetings() + " " + winCount);
					return true;
				}

			} catch (Exception e) {
				return false;
			}
		}
		return false;
	}

	private int getWinProbability(RedPacket packet) {
		int userWinProbability = userCoreService.getUser(packet.getUserId()).getWinProbability();
		if (userWinProbability != -1) {
			return userWinProbability;
		}
		int roomWinProbability = roomCoreDao.getRoomByJid(packet.getRoomJid()).getWinProbability();
		return roomWinProbability != -1 ? roomWinProbability : 50;
	}

	private double getWinProbabilityV2(RedPacket packet, double realProb) {
		String title = packet.getGreetings();
		int count = packet.getCount();
		int[] nums = getNums(title);
		int bombCount = nums.length;
		UserChanceSettings settingsByUserId = userChanceSettingsService.getSettingsByUserId(packet.getUserId());
		String settings;
		if(settingsByUserId == null){
			RoomChanceSettings settingsByJid = roomChanceSettingsService.getSettingsByJid(packet.getRoomJid());
			if(settingsByJid == null){
				UserChanceSettings defaultSettings = userChanceSettingsService.getDefaultSettings();
				if(packet.getMoney() >= defaultSettings.getBigStart()){
					settings = defaultSettings.getBigSettings();
				}else {
					settings = defaultSettings.getSettings();
				}
			}else {
				if(packet.getMoney() >= settingsByJid.getBigStart()){
					settings = settingsByJid.getBigSettings();
				}else {
					settings = settingsByJid.getSettings();
				}
			}
		}else {
			if(packet.getMoney() >= settingsByUserId.getBigStart()){
				settings = settingsByUserId.getBigSettings();
			}else {
				settings = settingsByUserId.getSettings();
			}
		}
		JSONObject jsonObject = JSONObject.parseObject(settings);
		return jsonObject.getDouble(count + "-" + bombCount);
	}

	public int[] randomCommon(int min, int max, int n) {
		if (max + 1 + 1 == n) {
			int[] result = new int[n - 1];
			for (int i = 0; i < n - 1; i++) {
				result[i] = i;
			}
			return result;
		}
		int len = max - min + 1;

		if (max < min || n > len) {
			return null;
		}

		//初始化给定范围的待选数组
		int[] source = new int[len];
		for (int i = min; i < min + len; i++) {
			source[i - min] = i;
		}

		int[] result = new int[n];
		Random rd = new Random();
		int index = 0;
		for (int i = 0; i < result.length; i++) {
			//待选数组0到(len-2)随机一个下标
			index = Math.abs(rd.nextInt() % len--);
			//将随机到的数放入结果集
			result[i] = source[index];
			//将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
			source[index] = source[len];
		}
//        Arrays.sort(result);
//        if (max!=n&&result[result.length-1]==max){
//            return randomCommon(min,max,n);
//        }
		return result;
	}

	private double getReallyProbability(RedPacket packet) {
		String title = packet.getGreetings();
		int count = packet.getCount();
		int[] nums = getNums(title);
		BigInteger n = new BigInteger(String.valueOf(count));
		BigInteger l = new BigInteger(String.valueOf(nums.length));
		BigInteger nine = new BigInteger("9");

		double reallyProbability = factorial(n).multiply(factorial(n.add(nine).subtract(l))).doubleValue() / (factorial(n.add(nine)).multiply(factorial(n.subtract(l)))).doubleValue();
		return reallyProbability;
	}

	public BigInteger factorial(BigInteger number) {
		BigInteger one = new BigInteger("1");
		if (number.compareTo(one) < 1)
			return one;
		else
			return number.multiply(factorial(number.subtract(one)));
	}

	private int[] getNums(String title) {
		StringBuilder builder = new StringBuilder("[");
		String pattern = "[^0-9]";
		Pattern r = Pattern.compile(pattern);
		Matcher m = r.matcher(title);
		while (m.find()) {
			String s = m.group();
			if (s.equals("\\")) {
				s = "\\\\";
			}
			builder.append(s);
		}
		builder.append("]");
		if (!builder.toString().equals("[]")) {
			String[] haveMoney = title.split(builder.toString());
			if (haveMoney.length == 2) {
				title = haveMoney[1];
			}
		}

		int[] nums;
		if (title.equals("财源滚滚，心想事成") || title.equals("恭喜发财,万事如意")) {
			nums = new int[1];
			nums[0] = 1;
		} else {
			try {
				nums = new int[title.length()];
				String[] split = title.split("");
				for (int i = 0; i < split.length; i++) {
					String s = split[i];
					nums[i] = Integer.parseInt(s);
				}
			} catch (NumberFormatException e) {
//                nums = getHaveMoneyNums(title);
//                if (title== null) {
//                    return null;
//                }
				return null;
			}
		}
		//去重
		HashSet<Integer> list = new HashSet<>();
		for (int num : nums) {
			list.add(num);
		}
		int[] newNums = new int[list.size()];
		int i = 0;
		for (Integer integer : list) {
			newNums[i] = integer;
			i++;
		}
		return newNums;
	}

	public Object sendRedPacketOnLock(int userId,RedPacket packet){



		packet.setUserId(userId);
		packet.setUserName(userCoreService.getNickName(userId));
		packet.setOver(packet.getMoney());
		long cuTime= DateUtil.currentTimeSeconds();
		packet.setSendTime(cuTime);
		packet.setOutTime(cuTime+ KConstants.Expire.DAY1);
		packet.setId(ObjectId.get());

		UserMoneyLog userMoneyLog =new UserMoneyLog(userId,packet.getToUserId(),packet.getId().toString(),packet.getMoney(),
				MoenyAddEnum.MOENY_REDUCE, MoneyLogEnum.REDPACKET, MoneyLogTypeEnum.NORMAL_PAY);

		//修改金额
		userCoreService.rechargeUserMoenyV1(userMoneyLog,balance -> {
			 saveRedPacket(packet);
			//开启一个线程 添加一条消费记录
			ThreadUtils.executeInThread(callback -> {
				String tradeNo= StringUtil.getOutTradeNo();
				//创建充值记录
				BaseConsumeRecord record=new BaseConsumeRecord();
				record.setUserId(userId);
				if (packet.getRoomJid()!=null && !packet.getRoomJid().isEmpty()) {
					Room room = roomManager.getRoomByJid(packet.getRoomJid());
//					log.info("========> room: {}", room);
					record.setToRoomJid(packet.getRoomJid());
					record.setToRoomName(room.getName());
				}
				if (packet.getToUserId() != 0) {
					User user = userCoreService.getUser(packet.getToUserId());
//					log.info("========> user: {}", user);
					record.setToUserId(packet.getToUserId());
					record.setToUserName(user.getNickname());
				}
				record.setTradeNo(tradeNo);
				record.setMoney(packet.getMoney());
				record.setStatus(KConstants.OrderStatus.END);
				record.setType(KConstants.ConsumeType.SEND_REDPACKET);
				record.setChangeType(KConstants.MOENY_REDUCE);
				record.setPayType(KConstants.PayType.BALANCEAY); //余额支付
				record.setDesc("红包发送");
				record.setTime(DateUtil.currentTimeSeconds());
				record.setRedPacketId(packet.getId());
				record.setOperationAmount(packet.getMoney());
				record.setCurrentBalance(balance);
				record.setBusinessId(userMoneyLog.getBusinessId());
//				log.info("====> record: {}", record);
				consumeRecordDao.addConsumRecord(record);
			});
			return true;

		});
		return packet;
	}
	
	public JSONMessage getRedPacketById(Integer userId, ObjectId id){

		RedPacket packet = getRedPacketById(id);
		if(null==packet) {
            return JSONMessage.failureByErrCode(KConstants.ResultCode.DataNotExists);
        }
		Map<String,Object> map=Maps.newHashMap();

		packet.setMoneyList(null);
		map.put("packet", packet);
		//判断红包是否超时
		if(DateUtil.currentTimeSeconds()>packet.getOutTime()){
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_TimeOut, map);
		}
			
		//判断红包是否已领完
		if(packet.getCount()>packet.getReceiveCount()){
			//判断当前用户是否领过该红包
			if(null==packet.getUserIds()||!packet.getUserIds().contains(userId)){
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.success(map);
			}else {
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacketReceived, map);
			}
		}else{//红包已经领完了
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_NoMore, map);
		}
	}
	/**
	 * 抢红包分布式锁
	 */
	private static final String REDPACK_LOCK = "redpack:lock:%s";
	
	public  JSONMessage openRedPacketById(Integer userId,ObjectId id){
		String redisKey = redPacketRedisService.buildRedisKey(REDPACK_LOCK, id.toString());
		try {
			return (JSONMessage) redPacketRedisService.executeOnLock(redisKey, callBack->
					openRedPacketByIdOnLock(userId,id));
		} catch (LockFailException e) {
			return JSONMessage.failureByErrCode(KConstants.ResultCode.SystemIsBusy);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			return JSONMessage.failureByErrCode(KConstants.ResultCode.SystemIsBusy);
		}
	}

	public  JSONMessage openRedPacketByIdOnLock(Integer userId,ObjectId id){
		RedPacket packet = getRedPacketById(id);
		if (null == packet) {
            return JSONMessage.failureByErrCode(KConstants.ResultCode.DataNotExists);
        }
		if (!StringUtil.isEmpty(packet.getYopRedPacketId())) {
			return JSONMessage.failureByErrCode(KConstants.ResultCode.DataNotExists);
		}
		Map<String,Object> map=Maps.newHashMap();
		map.put("packet", packet);
		// 群组红包判断
		if (packet.getRoomJid()!= null && !packet.getRoomJid().isEmpty()) {
			// 判断领取红包的用户是否被禁领红包
			Room room = roomManager.getRoomByJid(packet.getRoomJid());
			Room.Member member = roomManager.getMember(room.getId(), userId);
			log.info("===> room: {}, member: {}", room, member);
			if(member == null){
				return JSONMessage.failure("非群成员，请与群不可抢，管理员联系。");
			}
			if (member != null && room.getId().equals(member.getRoomId()) && member.getReceivePacketStatus().equals(0)) {
				return JSONMessage.failure("该群禁止您抢红包，请与群管理员联系。");
			}

			//判断是否为专属红包
			if (!packet.getRoomJid().isEmpty() && packet.getToUserId() != 0 && packet.getType() == 5) {
				if (!userId.equals(packet.getToUserId())) {
					return JSONMessage.failure("该红包为专属红包。");
				}
			}
		}



		//判断红包是否超时
		if(DateUtil.currentTimeSeconds()>packet.getOutTime()){
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_TimeOut,map);
		}
		//判断红包是否已领完
		if(packet.getCount()>packet.getReceiveCount()){
			//判断当前用户是否领过该红包
			//
			if(null==packet.getUserIds()||!packet.getUserIds().contains(userId)){
				packet=openRedPacket(userId, packet);
				map.put("packet", packet);
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.success(map);
			}
			else {
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacketReceived, map);
			}
		}else{ //你手太慢啦  已经被领完了
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_NoMore, map);
		}
	}
	
	private  RedPacket openRedPacket(Integer userId,RedPacket packet){
		int overCount= packet.getCount()-packet.getReceiveCount();
		User user=userCoreService.getUser(userId);
		double money=0.0;
		//普通红包
		if(1==packet.getType() || 5 == packet.getType()){
			if(1==packet.getCount()-packet.getReceiveCount()){
				//剩余一个  领取剩余红包
				money=packet.getOver();
			}else{
				money=packet.getMoney()/packet.getCount();
				//保留两位小数
				money= Double.parseDouble(DECIMAL_FORMAT.format(money));
			}
		}else if(4==packet.getType()){
			money=getMoneyByMoneyList(packet);
		}else{
			log.info("收起红包打开");
			//拼手气红包或者口令红包
			if (packet.getGreetings() != null && getNums(packet.getGreetings()) != null) {
				if (packet.isSenderWin()) {
					int win = packet.getWinCount().get(packet.getReceiveCount());
					if (win != -1) {
						int last2;
						do {
							money = getRandomMoney(overCount, packet.getOver());
							String moneyStr = String.valueOf(DECIMAL_FORMAT.format(money));
							last2 = Integer.parseInt(String.valueOf(moneyStr.charAt(moneyStr.indexOf(".") + 2)));
						} while (overCount != 1 && !(win == last2));
					} else {
						int userWinProbability = user.getWinProbability() == -1 ? 50 : user.getWinProbability();
						double reallyProbability = getNums(packet.getGreetings()).length * 1.0 / 10;
						double finalProbability = (reallyProbability + ((userWinProbability - 50) / 100.0) * 2 * (1 - reallyProbability)) * 100;
						System.out.println(userWinProbability + " " + reallyProbability + " " + finalProbability);
						double n = RANDOM.nextDouble();
						if (finalProbability >= n * 100) {
							int last2;
							do {
								money = getRandomMoney(overCount, packet.getOver());
								String moneyStr = String.valueOf(DECIMAL_FORMAT.format(money));
								last2 = Integer.parseInt(String.valueOf(moneyStr.charAt(moneyStr.indexOf(".") + 2)));
							} while (overCount != 1 && !intInInts(packet, last2));
						} else {
							int last2;
							do {
								money = getRandomMoney(overCount, packet.getOver());
								String moneyStr = String.valueOf(DECIMAL_FORMAT.format(money));
								last2 = Integer.parseInt(String.valueOf(moneyStr.charAt(moneyStr.indexOf(".") + 2)));
							} while (overCount != 1 && intInInts(packet, last2));
						}

					}
				} else {
					int last2;
					do {
						money = getRandomMoney(overCount, packet.getOver());
						String moneyStr = String.valueOf(DECIMAL_FORMAT.format(money));
						last2 = Integer.parseInt(String.valueOf(moneyStr.charAt(moneyStr.indexOf(".") + 2)));
					} while (overCount != 1 && boom(packet, last2));
				}
			} else {
				money = getRandomMoney(overCount, packet.getOver());
			}
		}
		
			
			// 保留两位小数
			Double over=(packet.getOver()-money);
			packet.setOver(Double.valueOf(DECIMAL_FORMAT.format(over)));
			packet.getUserIds().add(userId);
			Map<String,Object> map = new HashMap<>();
			if(0==packet.getOver()){
				map.put("status", 2);
				packet.setStatus(2);
			}
			map.put("receiveCount", packet.getReceiveCount()+1);
			map.put("over",packet.getOver());
			map.put("userIds", packet.getUserIds());
			updateRedPacket(packet.getId(),map);
			
		//实例化一个红包接受对象
		RedReceive receive=new RedReceive();
			receive.setMoney(money);
			receive.setUserId(userId);
			receive.setSendId(packet.getUserId());
			receive.setRedId(packet.getId());
			receive.setTime(DateUtil.currentTimeSeconds());
			receive.setUserName(userCoreService.getUser(userId).getNickname());
			receive.setSendName(userCoreService.getUser(packet.getUserId()).getNickname());
			receive.setId(ObjectId.get());
			saveRedReceive(receive);

		UserMoneyLog userMoneyLog =new UserMoneyLog(userId,packet.getUserId(),
				packet.getId().toString(),money,
				MoenyAddEnum.MOENY_ADD, MoneyLogEnum.REDPACKET, MoneyLogTypeEnum.RECEIVE);


			//修改金额
		    Double balance = userCoreService.rechargeUserMoenyV1(userMoneyLog);
		    final Double num=money;
			MessageBean messageBean=new MessageBean();
			messageBean.setType(MessageType.OPENREDPAKET);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(user.getNickname());
			if(packet.getRoomJid()!=null){
				messageBean.setObjectId(packet.getRoomJid());
				if(0==packet.getOver()) {
					messageBean.setFileSize(1);
					messageBean.setFileName(packet.getSendTime()+"");
				}
				messageBean.setRoomJid(packet.getRoomJid());
			}
			messageBean.setMsgType(null == packet.getRoomJid() ? 0 : 1);
			messageBean.setContent(packet.getId().toString());
			messageBean.setToUserId(packet.getUserId()+"");
			messageBean.setToUserName(userCoreService.getNickName(packet.getUserId()));
			messageBean.setMessageId(StringUtil.randomUUID());
			try {
				messageService.send(messageBean);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//开启一个线程 添加一条消费记录
			ThreadUtils.executeInThread(obj -> {
				String tradeNo=StringUtil.getOutTradeNo();
				//创建充值记录
				BaseConsumeRecord record=new BaseConsumeRecord();
				record.setUserId(userId);
				if (packet.getUserId() != 0) {
					User toUser = userCoreService.getUser(packet.getUserId());
					record.setToUserId(packet.getUserId());
					record.setToUserName(toUser.getNickname());
				}
				if (packet.getRoomJid() != null && !packet.getRoomJid().isEmpty()) {
					Room toRoom = roomManager.getRoomByJid(packet.getRoomJid());
					record.setToRoomJid(packet.getRoomJid());
					record.setToRoomName(toRoom.getName());
				}
				record.setTradeNo(tradeNo);
				record.setMoney(num);
				record.setStatus(KConstants.OrderStatus.END);
				record.setType(KConstants.ConsumeType.RECEIVE_REDPACKET);
				record.setChangeType(KConstants.MOENY_ADD);
				record.setPayType(KConstants.PayType.BALANCEAY); //余额支付
				record.setDesc("红包接收");
				record.setOperationAmount(num);
				record.setCurrentBalance(balance);
				record.setBusinessId(userMoneyLog.getBusinessId());
				record.setRedPacketId(packet.getId());
				record.setTime(DateUtil.currentTimeSeconds());
				consumeRecordDao.addConsumRecord(record);
			});
		return packet;
	}

	private boolean intInInts(RedPacket redPacket, int last2) {
		ArrayList<Integer> winCount = redPacket.getWinCount();
		for (int i = 0; i < winCount.size(); i++) {
			if (winCount.get(i) == last2) {
				winCount.set(i, -1);
				return true;
			}
		}
		return false;
	}

	public void updateRedPacket(ObjectId id, Map<String, Object> map){

		redPacketDao.updateRedPacket(id,map);
		redPacketRedisService.deleteRedPacket(id.toString());
	}

	private boolean boom(RedPacket redPacket, int number) {
		Set<Integer> n = new HashSet<>();
		int[] lei = getNums(redPacket.getGreetings());
		//判断当前是否炸
		for (int j : lei) {
			if (j == number) {
				n.add(number);
				break;
			}
		}
		//获取已中雷数
		List<RedReceive> moneyList = getRedReceivesByRedId(redPacket.getId());
		if (moneyList != null) {
			for (RedReceive receive : moneyList) {
				Double money = receive.getMoney();
				String moneyStr = DECIMAL_FORMAT.format(money);
				int last2 = Integer.parseInt(String.valueOf(moneyStr.charAt(moneyStr.indexOf(".") + 2)));
				for (int j : lei) {
					if (j == last2) {
						n.add(last2);
					}
				}
			}
		}
		return n.size() >= lei.length;
	}

	//发送领取红包消息  即 添加消费记录
	public void sendOpenMessageAndCreateRecord() {
		
	}

	private  final   Random RANDOM     = new Random();

	private final     DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.00");

	private  double getRandomMoney(int remainSize,Double remainMoney) {
		    // remainSize 剩余的红包数量
		    // remainMoney 剩余的钱
		double money=0.0;
		    if (remainSize == 1) {
		        remainSize--;
		         money=(double) Math.round(remainMoney * 100) / 100;
//		         System.out.println("=====> "+money);
	            return money;
		    }

		    double min   = 0.01; //
		    double max   = remainMoney / remainSize * 2;
		     money = RANDOM.nextDouble() * max;
		    money = money <= min ? 0.01: money;
		    money = Math.floor(money * 100) / 100;
//		    System.out.println("=====> "+money);
		    remainSize--;

		    remainMoney -= money;
		   return Double.valueOf(DECIMAL_FORMAT.format(money));
	}

	/**
	 * 固定金额红包
	 * @param packet
	 * @return
	 */
	private Double getMoneyByMoneyList(RedPacket packet){
		Double money;
		/**
		 * 用户应该领取金额的下标
		 */
		int size = packet.getMoneyList().size();

		int index = packet.getUserIds().size();
		if(index<=size-1){
			money=packet.getMoneyList().get(index);
		}else {
			log.info("红包金额的列表数量不足 count {} index {} moneyList size {} ",packet.getCount(),index,size);
			/**
			 * 规定列表数量不够
			 */
			money=packet.getMoneyList().get(size-1);
		}
		return money;
	}
	
	public void replyRedPacket(String id,String reply) {
		Integer userId = ReqUtil.getUserId();
		Map<String,Object> map = new HashMap<>();
		map.put("reply", reply);
		redReceiveDao.updateRedReceive(new ObjectId(id),userId,map);
		redPacketRedisService.deleteReceiveList(id);
	}
	
	//根据红包Id 获取该红包的领取记录
	public  List<RedReceive> getRedReceivesByRedId(ObjectId redId){
		String redpackId = redId.toString();
		List<RedReceive> redReceiveList = redPacketRedisService.queryReceiveList(redpackId);
		if(null==redReceiveList||0==redReceiveList.size()){
			redReceiveList=redReceiveDao.getRedReceiveList(redId);
			redPacketRedisService.saveReceiveList(redpackId,redReceiveList);
		}
		return redReceiveList;
	}
	//发送的红包
	public List<RedPacket> getSendRedPacketList(Integer userId,int pageIndex,int pageSize){
		return redPacketDao.getRedPacketList(userId,pageIndex,pageSize);
	}
	//收到的红包
	public List<RedReceive> getRedReceiveList(Integer userId,int pageIndex,int pageSize){
		return redReceiveDao.getRedReceiveList(userId,pageIndex,pageSize);
	}
	
	
	//发送的红包
	public PageResult<RedPacket> getRedPacketList(String userName, int pageIndex, int pageSize, String redPacketId){
		return redPacketDao.getRedPackListPageResult(userName,redPacketId,pageIndex,pageSize);
	}
	
	//发送的红包
	public PageResult<RedReceive> receiveWater(String redId,int pageIndex,int pageSize){
		return redReceiveDao.getRedReceivePageResult(new ObjectId(redId),pageIndex,pageSize);
	}

	public RedPacket getRedPacketByPoy(String yopRedPacketId){
		return redPacketDao.getRedPacketByPoy(yopRedPacketId);
	}

	public RedPacket getRedPacketById(ObjectId id){
		String redpackId = id.toString();
		RedPacket redPacket=redPacketRedisService.queryRedPacket(redpackId);
		if(null==redPacket){
			redPacket=redPacketDao.getRedPacketById(id);
			if(null!=redPacket){
				redPacketRedisService.saveRedPacket(redpackId,redPacket);
			}
		}

		return redPacket;
	}

	public void saveRedReceive(RedReceive receive){
		 redReceiveDao.addRedReceive(receive);

		 redPacketRedisService.deleteReceiveList(receive.getRedId().toString());
	}


	@Override
	public Object getRedPackListTimeOut(long outTime, int status) {
		return redPacketDao.getRedPackListTimeOut(outTime,status);
	}

	@Override
	public void updateRedPackListTimeOut(long outTime, int status, Map<String, Object> map) {
		redPacketDao.updateRedPackListTimeOut(outTime,status,map);
	}


	public static final int STATUS_START=1;//红包发出状态
	public static final int STATUS_END=2;//已领完红包状态
	public static final int STATUS_RECEDE=-1;//已退款红包状态

	@Override
	public void autoRefreshRedPackect() {
		long currentTime=DateUtil.currentTimeSeconds();
		Integer userId=0;
		Integer toUserId=0;
		String roomJid="";
		ObjectId redPackectId=null;
		Double money=0.0;
		List<RedPacket> redPackets = redPacketDao.getRedPackListTimeOut(currentTime,STATUS_START);

		for (RedPacket redPacket : redPackets) {

			try {
				recedeMoney(redPacket);
			} catch (Exception e) {
				continue;
			}
		}
        if(0<redPackets.size()){
            Map<String,Object> map = new HashMap<>();
            map.put("status",STATUS_RECEDE);
            redPacketDao.updateRedPackListTimeOut(currentTime,STATUS_START,map);
        }

		log.info("红包超时未领取的数量 ======> "+redPackets.size());
	}



	private void recedeMoney(RedPacket redPacket){
		Double money=0.0;
		if(0<redPacket.getOver()){
			DecimalFormat df = new DecimalFormat("#.00");
			money= Double.valueOf(df.format(redPacket.getOver()));
		}else {
			return;
		}
		//实例化一天交易记录
		 ConsumeRecord record=new ConsumeRecord();
		String tradeNo= com.shiku.im.comm.utils.StringUtil.getOutTradeNo();
		record.setTradeNo(tradeNo);
		record.setMoney(money);
		record.setOperationAmount(money);


		UserMoneyLog userMoneyLog =new UserMoneyLog(redPacket.getUserId(),redPacket.getToUserId(),
				redPacket.getId().toString(),money,
				MoenyAddEnum.MOENY_ADD, MoneyLogEnum.REDPACKET, MoneyLogTypeEnum.REFUND);

		userCoreService.rechargeUserMoenyV1(userMoneyLog,balance->{
			redPacketRedisService.deleteRedPacket(redPacket.getId().toString());
			record.setUserId(redPacket.getUserId());
			record.setToUserId(redPacket.getToUserId());
			record.setType(KConstants.ConsumeType.REFUND_REDPACKET);
			record.setChangeType(KConstants.MOENY_ADD);
			record.setPayType(KConstants.PayType.BALANCEAY);
			record.setTime(DateUtil.currentTimeSeconds());
			record.setStatus(KConstants.OrderStatus.END);
			record.setDesc("红包退款");
			record.setRedPacketId(redPacket.getId());

			record.setCurrentBalance(balance);
			record.setBusinessId(userMoneyLog.getBusinessId());
			consumeRecordDao.addConsumRecord(record);
			return true;
		});

		User toUser = userCoreService.getUser(redPacket.getUserId());
		MessageBean messageBean=new MessageBean();
		messageBean.setType(MessageType.RECEDEREDPAKET);
		if(toUser!=null){
			messageBean.setFromUserId(toUser.getUserId().toString());
			messageBean.setFromUserName(toUser.getNickname());
		}else {
			messageBean.setFromUserId("10100");
			messageBean.setFromUserName("支付公众号");
		}

		if(redPacket.getRoomJid()!=null){
			messageBean.setObjectId(redPacket.getRoomJid());
		}
		messageBean.setContent(redPacket.getId().toString());
		messageBean.setToUserId(redPacket.getUserId()+"");
		// 单聊消息
		messageBean.setMsgType(0);
		messageBean.setMessageId(com.shiku.im.comm.utils.StringUtil.randomUUID());
		try {
			messageService.send(messageBean);
		} catch (Exception e) {
			e.printStackTrace();
		}

		log.info(redPacket.getUserId()+"  发出的红包,剩余金额   "+money+"  未领取  退回余额!");
	}

	@Override
	public String queryRedpackOverGroupCount(long startTime, long endTime) {
		return redPacketDao.queryRedpackOverGroupCount(startTime,endTime);
	}

	@Override
	public JSONMessage editReceivePacketStatus(String jid, int toUserId) {
		try {
			Integer userId = ReqUtil.getUserId();
			Room room = roomManager.getRoomByJid(jid);
			Room.Member member = roomManager.getMember(room.getId(), toUserId);
			if (member.getRole() == 1 || member.getRole() == 2) {
				return JSONMessage.failure("不能禁止群主或管理员抢红包");
			}
			if (member.getReceivePacketStatus().equals(0)) {
				member.setReceivePacketStatus(1);
			} else {
				member.setReceivePacketStatus(0);
			}
			roomManager.updateMemberReceivePacketStatus(userCoreService.getUser(userId), room.getId(), member);
			return JSONMessage.success("修改成功");

		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONMessage.failure("接口内部异常");
	}

	@Override
	public JSONMessage getReceivePacketStatus(String jid, int userId) {
		try {
			Room room = roomManager.getRoomByJid(jid);
			Room.Member member = roomManager.getMember(room.getId(), userId);
			Map data = new HashMap();
			data.put("receivePacketStatus", member.getReceivePacketStatus());
			return JSONMessage.success(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONMessage.failure("接口内部异常");
	}

	@Override
	public JSONMessage banAllReceivePacketStatus(int userId, String jid) {
		try {

			Room room = roomManager.getRoomByJid(jid);
			List<Room.Member> memberList = roomManager.getMemberList(room.getId(), null);
			for (Room.Member member : memberList) {
				if (member.getRole() == 1 || member.getRole() == 2 || member.getUserId().equals(1010)) {
					continue;
				}
				member.setReceivePacketStatus(0);
				roomManager.updateMemberReceivePacketStatus(userCoreService.getUser(userId), room.getId(), member);
			}

			return JSONMessage.success("修改成功");

		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONMessage.failure("接口内部异常");
	}

	@Override
	public JSONMessage allowAllReceivePacketStatus(int userId, String jid) {
		try {
			Room room = roomManager.getRoomByJid(jid);
			List<Room.Member> memberList = roomManager.getMemberList(room.getId(), null);
			for (Room.Member member : memberList) {
				if (member.getRole() == 1 || member.getRole() == 2) {
					continue;
				}
				member.setReceivePacketStatus(1);
				roomManager.updateMemberReceivePacketStatus(userCoreService.getUser(userId), room.getId(), member);
			}

			return JSONMessage.success("修改成功");

		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONMessage.failure("接口内部异常");
	}

	@Override
	public JSONMessage getAllReceivePacketStatus(String jid) {
		try {
			Room room = roomManager.getRoomByJid(jid);
			List<Room.Member> memberList = roomManager.getMemberList(room.getId(), null);
			List data = new ArrayList();
			for (Room.Member member : memberList) {
				Map receivePacketStatus = new HashMap();
				receivePacketStatus.put("userId", member.getUserId());
				receivePacketStatus.put("status", member.getReceivePacketStatus());
				data.add(receivePacketStatus);
			}

			return JSONMessage.success(data);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONMessage.failure("接口内部异常");
	}
}
